package main.components;

import main.FactageSmet;
import main.components.renderers.CellRendererSmetHead;
import main.MainFrame;
import main.MsSQLConnect;
import main.SetActualSmet;
import main.objects.*;
import org.jdom2.Element;
import sun.applet.Main;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.*;
import java.text.*;
import java.util.*;
import java.util.Date;

public class TreeSmet extends JTree {

    private JPopupMenu contextMenu;

    public SmetNode ROOT_SMET_NODE;
    public TreeTitulNode CURRENT_TITUL_NODE;
    public SmetNode SELECTED_SMET;

    public DefaultTreeModel treeModel;
    private Statement stat;
    private SmetNode actualSmet;
    private Date dateChange;

    //region Конструктор
    public TreeSmet() {
        initTree();
    }
    //endregion

    //region Инициализация компонента
    private void initTree() {

        ROOT_SMET_NODE = new SmetNode(0, "Выберите EPS");
        treeModel = new DefaultTreeModel(ROOT_SMET_NODE);
        setModel(treeModel);
        setRowHeight(0);
        setCellRenderer(new MyTableInTreeCellRenderer());

        //region Контекстное меню
        contextMenu = new JPopupMenu();

        JMenuItem renameNodeItem = new JMenuItem("Переименовать Смету");
        renameNodeItem.setIcon(new ImageIcon(getClass().getResource("icons/rename12x12.png")));
        renameNodeItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0));
        renameNodeItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                renameSmet();
            }
        });
        contextMenu.add(renameNodeItem);

        contextMenu.add(new JPopupMenu.Separator());

        JMenuItem copyNodeItem = new JMenuItem("Копировать Смету");
        copyNodeItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                copySmetToBuffer();
            }
        });
        contextMenu.add(copyNodeItem);

        JMenuItem cutNodeItem = new JMenuItem("Вырезать Смету");
        cutNodeItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                cutSmetToBuffer();
            }
        });
        contextMenu.add(cutNodeItem);

        JMenuItem pasteNodeItem = new JMenuItem("Вставить Смету");
        pasteNodeItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                pasteSmet();
            }
        });
        contextMenu.add(pasteNodeItem);

        contextMenu.add(new JPopupMenu.Separator());

        JMenuItem removeNodeItem = new JMenuItem("Удалить Смету");
        removeNodeItem.setIcon(new ImageIcon(getClass().getResource("icons/delete12x12.png")));
        removeNodeItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                removeNodeDialogShow();
            }
        });
        removeNodeItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
        contextMenu.add(removeNodeItem);

        //endregion

        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent mouseEvent) {
                if (mouseEvent.getButton() == 3) {
                    popupMenuOpen(mouseEvent.getX(), mouseEvent.getY());
                }
            }
        });

        addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent keyEvent) {

            }

            @Override
            public void keyPressed(KeyEvent keyEvent) {
                if (keyEvent.getKeyCode() == KeyEvent.VK_F2) {
                    renameSmet();
                } else if (keyEvent.getKeyCode() == KeyEvent.VK_DELETE) {
                    removeNodeDialogShow();
                }
            }

            @Override
            public void keyReleased(KeyEvent keyEvent) {

            }
        });

        addTreeExpansionListener(new TreeExpansionListener() {
            @Override
            public void treeExpanded(TreeExpansionEvent treeExpansionEvent) {

                SmetNode curNode = (SmetNode) treeExpansionEvent.getPath().getLastPathComponent();

                if (curNode.isSmet() && curNode.getNextSibling() != null) {
                    SmetNode sibl = (SmetNode) curNode.getNextSibling();
                    sibl.smetUnderExpanded = true;
                }

            }

            @Override
            public void treeCollapsed(TreeExpansionEvent treeExpansionEvent) {

                SmetNode curNode = (SmetNode) treeExpansionEvent.getPath().getLastPathComponent();

                if (curNode.isSmet() && curNode.getNextSibling() != null) {
                    SmetNode sibl = (SmetNode) curNode.getNextSibling();
                    sibl.smetUnderExpanded = false;
                }

            }
        });

        addTreeSelectionListener(new TreeSelectionListener() {
            @Override
            public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
                SELECTED_SMET = (SmetNode) getLastSelectedPathComponent();
            }
        });

    }
    //endregion

    public void copySmetToBuffer() {

        TreePath[] selectPaths = this.getSelectionPaths();
        if (selectPaths.length < 1) return;

        MainFrame.BUFFER_CUT = new ArrayList<>();
        MainFrame.BUFFER_COPY = new ArrayList<>();

        for (TreePath path : selectPaths) {

            SmetNode tempSmet = (SmetNode) path.getLastPathComponent();
            if (tempSmet!=null && tempSmet.isSmet())
            MainFrame.BUFFER_COPY.add(tempSmet);

        }

    }

    public void cutSmetToBuffer() {

        TreePath[] selectPaths = this.getSelectionPaths();
        if (selectPaths.length < 1) return;

        MainFrame.BUFFER_CUT = new ArrayList<>();
        MainFrame.BUFFER_COPY = new ArrayList<>();

        for (TreePath path : selectPaths) {

            SmetNode tempSmet = (SmetNode) path.getLastPathComponent();
            if (tempSmet!=null && tempSmet.isSmet()) MainFrame.BUFFER_CUT.add(tempSmet);

        }

    }

    public void pasteSmet() {

        if (MainFrame.SELECTED_EPS.isEPS) {

            if (!MainFrame.BUFFER_CUT.isEmpty()) {

                for (SmetNode pasteSmet : MainFrame.BUFFER_CUT) {

                    if (MainFrame.ALL_EPS.containsKey(pasteSmet.getEpsId() + "-eps")) {
                        if (MainFrame.ALL_EPS.get(pasteSmet.getEpsId() + "-eps").getSmets().size() < 3)
                            MainFrame.ALL_EPS.get(pasteSmet.getEpsId() + "-eps").getSmets().remove(MainFrame.ALL_SMET.get("smethead"));

                        MainFrame.ALL_EPS.get(pasteSmet.getEpsId() + "-eps").getSmets().remove(pasteSmet);
                    }

                    pasteSmet.setEpsId(MainFrame.SELECTED_EPS.getId());
                    pasteSmet.setTitulId(MainFrame.SELECTED_EPS.getTitulId());
                    pasteSmet.updateSmetEPS();

                }

            } else {

                for (SmetNode pasteSmet : MainFrame.BUFFER_COPY) {

                    //pasteSmet.copySmet();

                }

            }

        }

    }

    public void renameSmet() {

        new RenameSmetDialog((SmetNode) this.getLastSelectedPathComponent());

    }

    public void reloadModel() {
        treeModel.reload();
    }

    //region Отображение контекстного меню
    private void popupMenuOpen(int X, int Y) {

        SELECTED_SMET = null;
        contextMenu.getComponent(0).setEnabled(false);
        contextMenu.getComponent(2).setEnabled(false);
        contextMenu.getComponent(3).setEnabled(false);
        contextMenu.getComponent(4).setEnabled(false);
        contextMenu.getComponent(6).setEnabled(false);

        int row = this.getRowForLocation(X, Y);

        if (row >= 0) {

            contextMenu.show(this, X, Y);
//            this.setSelectionInterval(row, row);
            SELECTED_SMET = (SmetNode) this.getLastSelectedPathComponent();
            contextMenu.getComponent(0).setEnabled(SELECTED_SMET != null && SELECTED_SMET.isSmet());
            contextMenu.getComponent(2).setEnabled(SELECTED_SMET != null && SELECTED_SMET.isSmet());
            contextMenu.getComponent(3).setEnabled(SELECTED_SMET != null && SELECTED_SMET.isSmet());
            contextMenu.getComponent(4).setEnabled(!MainFrame.BUFFER_COPY.isEmpty() || !MainFrame.BUFFER_CUT.isEmpty());
            contextMenu.getComponent(6).setEnabled(SELECTED_SMET != null && SELECTED_SMET.isSmet());

        }
    }
    //endregion

    private void removeNodeDialogShow() {

        FactageSmet.IMPORT_FACTAGE_CONNECTION = MsSQLConnect.ConnectDB("ImportFactage");

        try {

            stat = FactageSmet.IMPORT_FACTAGE_CONNECTION.createStatement();

            int dialogButton = JOptionPane.YES_NO_OPTION;
            int dialogResult = JOptionPane.showConfirmDialog (null, "Вы действительно хотите удалить смету \"" + SELECTED_SMET.getNum() + "\"? ","Удаление", dialogButton);
            if (dialogResult == JOptionPane.YES_OPTION) {
//                if (SELECTED_SMET.getChange() > 0) {
//                    for (SmetNode oldSmet : MainFrame.ALL_SMET.values()) {
//                        if (oldSmet.isSmet() && oldSmet.getNauka_id() == SELECTED_SMET.getNauka_id() && oldSmet.getChange() == SELECTED_SMET.getChange() - 1) {
//                            stat.executeUpdate("UPDATE [Factage].[dbo].[link] SET actual = 1 FROM [Factage].[dbo].[link] as l LEFT JOIN [importFactage].[dbo].[Smr] as s on s.id = l.smr_id WHERE l.importFactage = 'true' and s.smet_id = " + oldSmet.getId());
//                            stat.executeUpdate("update [importFactage].[dbo].[Smet] set status = 'Актуальная' WHERE id = " + oldSmet.getId());
//                            oldSmet.setStatus("Актуальная");
//                        }
//                    }
//                }

                stat.executeUpdate("DELETE FROM Smet WHERE id = " + SELECTED_SMET.getId());

                ROOT_SMET_NODE.remove(SELECTED_SMET);
                SELECTED_SMET.removeAllChildren();
                MainFrame.ALL_SMET.get(SELECTED_SMET.getId() + "-smet").removeAllChildren();
                MainFrame.ALL_SMET.get(SELECTED_SMET.getId() + "-smet").removeFromParent();
                MainFrame.ALL_SMET.remove(SELECTED_SMET.getId() + "-smet");
                MainFrame.ALL_EPS.get(CURRENT_TITUL_NODE.getId() + "-eps").getSmets().remove(SELECTED_SMET);
                treeModel.reload();
            }

            stat.close();
            FactageSmet.IMPORT_FACTAGE_CONNECTION.close();

        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    public JTree getTree() {
        return this;
    }

    public void showSmet(TreeTitulNode curNode) {

        this.CURRENT_TITUL_NODE = curNode;
        ROOT_SMET_NODE = new SmetNode(0, CURRENT_TITUL_NODE.getName());
        treeModel.setRoot(ROOT_SMET_NODE);

        if (CURRENT_TITUL_NODE.getSmets().size() > 0) {
            for (SmetNode smet : CURRENT_TITUL_NODE.getSmets()) {
                ROOT_SMET_NODE.add(smet);
            }
            treeModel.reload();
        }

    }

    public void dialogChooseActualSmet(int newSmetId) {

        SmetNode newSmet = MainFrame.ALL_SMET.get(newSmetId + "-smet");
        if (actualSmet != null) {
            ArrayList<SmetNode> newSmetList = new ArrayList<>();
            for (SmetNode smr : newSmet.getChildren()) {
                if (smr.isSmr()) newSmetList.add(smr);
            }

            ArrayList<SmetNode> actualSmetList = new ArrayList<>();
            for (SmetNode smr : actualSmet.getChildren()) {
                if (smr.isSmr()) actualSmetList.add(smr);
            }

            SetActualSmet setActualSmet = new SetActualSmet(actualSmet, newSmet, newSmetList, actualSmetList);
            setActualSmet.showDialog();
        }
    }

}

class MyTableInTreeCellRenderer extends JPanel implements TreeCellRenderer {

    private static final long serialVersionUID = 1L;
    private JTable table;
    private DateFormat dateFormat;

    public MyTableInTreeCellRenderer() {

        super(new BorderLayout());
        table = new JTable();
        add(table);

    }

    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {

        final String v = (String) ((SmetNode) value).getUserObject();
        final SmetNode curNode = (SmetNode) value;
        final SmetNode node = MainFrame.ALL_SMET.get(v);
        dateFormat = new SimpleDateFormat("dd-MM-yy");

        Border bord = BorderFactory.createEmptyBorder(10, 0, 0, 0);
        Border bottomBord = BorderFactory.createEmptyBorder(0, 0, 25, 0);
        Border borderNone = BorderFactory.createEmptyBorder(0, 0, 0, 0);
        Border sectBord = BorderFactory.createEmptyBorder(5, 0, 5, 0);

        if (node != null && !node.equals(MainFrame.treeSmet.ROOT_SMET_NODE)) {

            if (node.isHeadSmr()) {
                setBorder(bord);
                setBackground(Color.white);
            } else if (node.isSmr() || node.isSmet()) {
                setBorder(borderNone);
                if (node.isSmr() && node.isLast()) setBorder(bottomBord);
            } else if (node.isHeadSmet()) {
                setBorder(bord);
                setBackground(Color.white);
            } else if (node.isChapter() || node.isHeader()) {
                setBorder(sectBord);
            } else {
                setBorder(borderNone);
            }
        } else {
            setBorder(borderNone);
        }

        if (selected) table.setBackground(Color.orange);
        else table.setBackground(Color.white);

        table.setModel(new DefaultTableModel() {

            private static final long serialVersionUID = 1L;

            @Override
            public int getRowCount() {
                return 1;
            }

            @Override
            public int getColumnCount() {
                if (node != null) {
                    if (node.isSmet() || node.isHeadSmet()) {
                        return 7;
                    } else if (node.isSmr() || node.isHeadSmr()) {
                        return 8;
                    }
                }
                return 1;
            }

            @Override
            public Object getValueAt(int row, int column) {

                DecimalFormat df = new DecimalFormat();
                DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(Locale.getDefault());
                otherSymbols.setDecimalSeparator('.');
                otherSymbols.setGroupingSeparator(' ');

                df.setMaximumFractionDigits(4);
                df.setMinimumFractionDigits(2);
                df.setGroupingUsed(true);
                df.setDecimalFormatSymbols(otherSymbols);

                if (node != null) {
                    if (node.isSmet()) {
                        switch (column) {
                            case 0:
                                return node.getNum();
                            case 1:
                                return node.getName();
                            case 2:
                                return node.getStatus();
                            case 3:
                                return df.format(node.getSum());
                            case 4:
                                return df.format(node.getPz());
                            case 5:
                                return node.getChange();
                            case 6:
                                return (node.getDateChange() != null ? dateFormat.format(node.getDateChange()) : "");

                            default:
                                return "---";
                        }
                    } else if (node.isHeadSmet()) {
                        switch (column) {
                            case 0:
                                return "Номер сметы";
                            case 1:
                                return "Наименование";
                            case 2:
                                return "ПЗ";
                            case 3:
                                return "Стоимость";
                            case 4:
                                return "Статус";
                            case 5:
                                return "Изм.";
                            case 6:
                                return "Дата изм.";

                            default:
                                return "---";
                        }
                    } else if (node.isSmr()) {

                        switch (column) {
                            case 0:
                                return node.getSmrNum();
                            case 1:
                                return node.getCode();
                            case 2:
                                return node.getName();
                            case 3:
                                return node.getUnit();
                            case 4:
                                return df.format(node.getVolume());
                            case 5:
                                return df.format(node.getPz());
                            case 6:
                                return df.format(node.getOz());
                            case 7:
                                return df.format(node.getEm());
                            default:
                                return "---";
                        }
                    } else if (node.isHeadSmr()) {
                        switch (column) {
                            case 0:
                                return "№";
                            case 1:
                                return "Наименование";
                            case 2:
                                return "Код расценки";
                            case 3:
                                return "Ед. Изм.";
                            case 4:
                                return "Объем";
                            case 5:
                                return "Т-ты";
                            case 6:
                                return "М-мы";
                            case 7:
                                return "ПЗ";
                            default:
                                return "---";
                        }
                    } else if (node.isChapter() || node.isHeader()) {
                        switch (column) {
                            case 0:
                                return "Раздел " + (node.isChapter() ? node.getName() + " - "  : "") + node.getName();
                            default:
                                return "---";
                        }
                    }
                }
                return curNode.getName() != null && curNode.getName().equals("Выберите EPS") ? "Выберите EPS" : "Раздел EPS - " + curNode.getName();
            }

        });

        //tree.setRowHeight(0);
        table.getTableHeader().setVisible(false);
        //table.setPreferredScrollableViewportSize(table.getPreferredSize());
        if (node != null) {

            if (node.isSmet()) {

                table.getColumnModel().getColumn(0).setMinWidth(250);
                table.getColumnModel().getColumn(0).setMaxWidth(260);
                table.getColumnModel().getColumn(1).setMinWidth(450);
                table.getColumnModel().getColumn(1).setMaxWidth(550);
                table.getColumnModel().getColumn(3).setMinWidth(100);
                table.getColumnModel().getColumn(3).setMaxWidth(100);
                table.getColumnModel().getColumn(5).setMinWidth(30);
                table.getColumnModel().getColumn(5).setMaxWidth(30);

                if (!node.smetUnderExpanded) table.setBorder(BorderFactory.createMatteBorder( 0, 1, 0, 0, table.getGridColor()));
                else table.setBorder(BorderFactory.createMatteBorder( 1, 1, 0, 0, table.getGridColor()));

                table.setShowGrid(true);
                table.setFont(new Font("Calibri", 0, 12));

            } else if (node.isSmr()) {

                table.getColumnModel().getColumn(0).setMinWidth(40);
                table.getColumnModel().getColumn(0).setMaxWidth(50);
                table.getColumnModel().getColumn(1).setMinWidth(150);
                table.getColumnModel().getColumn(1).setMaxWidth(250);
                table.getColumnModel().getColumn(2).setMinWidth(550);
                table.getColumnModel().getColumn(2).setMaxWidth(850);
                table.setBorder(BorderFactory.createMatteBorder( 0, 1, 0, 0, table.getGridColor()));
                table.setShowGrid(true);
                table.setFont(new Font("Calibri", 0, 12));

            } else if (node.isHeadSmet()) {

                table.getColumnModel().getColumn(0).setMinWidth(250);
                table.getColumnModel().getColumn(0).setMaxWidth(260);
                table.getColumnModel().getColumn(1).setMinWidth(450);
                table.getColumnModel().getColumn(1).setMaxWidth(550);
                table.getColumnModel().getColumn(3).setMinWidth(100);
                table.getColumnModel().getColumn(3).setMaxWidth(100);
                table.getColumnModel().getColumn(5).setMinWidth(30);
                table.getColumnModel().getColumn(5).setMaxWidth(30);

                table.setBorder(BorderFactory.createMatteBorder( 1, 1, 0, 0, table.getGridColor()));
                for (int i = 0; i < table.getColumnModel().getColumnCount(); i++) {
                    table.getColumnModel().getColumn(i).setCellRenderer(new CellRendererSmetHead());
                }
                table.setShowGrid(true);
                table.setFont(new Font("Calibri", 0, 12));

            } else if (node.isHeadSmr()) {

                table.getColumnModel().getColumn(0).setMinWidth(40);
                table.getColumnModel().getColumn(0).setMaxWidth(50);
                table.getColumnModel().getColumn(1).setMinWidth(150);
                table.getColumnModel().getColumn(1).setMaxWidth(250);
                table.getColumnModel().getColumn(2).setMinWidth(550);
                table.getColumnModel().getColumn(2).setMaxWidth(850);
                table.setBorder(BorderFactory.createMatteBorder( 1, 1, 0, 0, table.getGridColor()));
                for (int i = 0; i < 8; i++) {
                    table.getColumnModel().getColumn(i).setCellRenderer(new CellRendererSmetHead());
                }
                table.setShowGrid(true);
                table.setFont(new Font("Calibri", 0, 12));

            } else if (node.isChapter() || node.isHeader()) {

                table.getColumnModel().getColumn(0).setMinWidth(950);
                table.getColumnModel().getColumn(0).setMaxWidth(950);
                table.setBorder(BorderFactory.createEmptyBorder());
                if (selected) table.setBackground(Color.orange);
                else table.setBackground(new Color(214, 218, 210));

                table.setShowGrid(false);
                table.setFont(new Font("Calibri", Font.BOLD, 12));

            }

        } else {

            table.getColumnModel().getColumn(0).setMinWidth(550);
            table.getColumnModel().getColumn(0).setMaxWidth(750);
            table.setBorder(BorderFactory.createEmptyBorder());
            table.setShowGrid(false);
            table.setFont(new Font("Segoe UI", Font.BOLD, 18));
            table.setRowHeight(20);

        }
        return this;

    }
}